package com.yn.sample.visitor.impl;

import com.yn.sample.domain.MethodCodeStackSizeAndLocalVariablesTableSize;
import com.yn.sample.domain.MethodInfo;
import com.yn.sample.visitor.ClassMethodCodeVisitor;
import com.yn.sample.visitor.ClassMethodInfoVisitor;
import com.yn.sample.domain.MethodInstructionVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.LinkedHashMap;
import java.util.List;

@Component
public class ClassMethodInfoVisitorImpl implements ClassMethodInfoVisitor {
    @Autowired
    private ClassMethodCodeVisitor classMethodCodeVisitor;

    /**
     * 当前正在访问的方法的签名
     */
    private String methodInVisitNow;

    /**
     * 方法map，
     * key:方法签名 value：方法的全部信息
     *
     * MethodInfo中会封装方法的全部信息，也就是class反编译后的如下部分：
     * public com.yn.method.CheckAndSet();
     *     descriptor: ()V
     *     flags: ACC_PUBLIC
     *     Code:
     *       stack=1, locals=1, args_size=1
     *          0: aload_0
     *          1: invokespecial #1                  // Method java/lang/Object."<init>":()V
     *          4: return
     *       LineNumberTable:
     *         line 3: 0
     *       LocalVariableTable:
     *         Start  Length  Slot  Name   Signature
     *             0       5     0  this   Lcom/yn/method/CheckAndSet;
     */
    private LinkedHashMap<String,MethodInfo> methodInfoMap = new LinkedHashMap<>();


    @Override
    public void visitMethodStart() {

    }

    @Override
    public void visitMethodName(String name) {
        MethodInfo info = new MethodInfo();
        info.setSignature(name);

        methodInfoMap.put(name,info);

        methodInVisitNow = name;


    }

    @Override
    public void visitMethodDescriptor(String descriptor) {

    }

    @Override
    public void visitFlags(String flags) {

    }

    @Override
    public ClassMethodCodeVisitor visitMethodCode() {
        return classMethodCodeVisitor;
    }

    @Override
    public void visitMethodEnd() {
        /**
         * 代表一个方法解析完成
         * 此时，取到指令集合，设置到MethodInfo的属性中去
         */
        MethodInfo methodInfo = methodInfoMap.get(methodInVisitNow);
        List<MethodInstructionVO> instructions = classMethodCodeVisitor.getInstructions();
        methodInfo.setInstructionVOList(instructions);

        MethodCodeStackSizeAndLocalVariablesTableSize obj =
                classMethodCodeVisitor.getMethodCodeStackSizeAndLocalVariablesTableSize();
        methodInfo.setMethodCodeStackSizeAndLocalVariablesTableSize(obj);

        classMethodCodeVisitor.newInstructionList();
    }

    @Override
    public LinkedHashMap<String, MethodInfo> getMethodInfoMap() {
        return methodInfoMap;
    }
}
